package com.base.api.service.selfOrder;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.base.api.dto.selfOrder.OrderConfirmPayDTO;
import com.base.api.dto.selfOrder.PartakerConfirmPayDTO;
import com.base.exception.BaseException;
import com.base.mapper.voipmapper.SubscribersMapper;
import com.base.po.voip.Subscribers;
import com.base.result.ResponseResultUtils;
import com.base.self.common.LockStockService;
import com.base.self.common.OrderGenContext;
import com.base.self.common.SelfRuntimeException;
import com.base.self.common.SelfRuntimeOkException;
import com.base.self.entity.*;
import com.base.self.mapper.CommodityMapper;
import com.base.self.mapper.PayDealMapper;
import com.base.self.mapper.PtintegralMapper;
import com.base.self.mapper.SelfOrderMapper;
import com.base.self.service.IPtCurrentService;
import com.base.self.service.IPtintegralService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.Optional;

@Service
@Slf4j
public class SelfOrderApiCommonServer {

    Logger logger = LoggerFactory.getLogger(SelfOrderApiCommonServer.class);

    private final SubscribersMapper subscribersMapper;

    private final CommodityMapper commodityMapper;

    private final IPtintegralService iPtintegralService;

    private final PtintegralMapper ptintegralMapper;

    private final IPtCurrentService iPtCurrentService;

    private final PayDealMapper payDealMapper;

    private final SelfOrderMapper selfOrderMapper;

    private final LockStockService lockStockService;

    public SelfOrderApiCommonServer(SubscribersMapper subscribersMapper,
                                    CommodityMapper commodityMapper,
                                    IPtintegralService iPtintegralService,
                                    PtintegralMapper ptintegralMapper,
                                    IPtCurrentService iPtCurrentService,
                                    PayDealMapper payDealMapper,
                                    SelfOrderMapper selfOrderMapper,
                                    LockStockService lockStockService) {
        this.subscribersMapper = subscribersMapper;
        this.commodityMapper = commodityMapper;
        this.iPtintegralService = iPtintegralService;
        this.ptintegralMapper = ptintegralMapper;
        this.iPtCurrentService = iPtCurrentService;
        this.payDealMapper = payDealMapper;
        this.selfOrderMapper = selfOrderMapper;
        this.lockStockService = lockStockService;
    }

    public void deductExpenses(final String context, final String userId, final BigDecimal needMoney/*需要扣掉的*/){
        if (needMoney.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        final BigDecimal freeze = iPtintegralService.getTotalMoneyByUserId(userId, 1)/*冻结的*/;
        //final BigDecimal noFreeze = iPtintegralService.getTotalMoneyByUserId(userId, 0)/*正常的*/;
        if (freeze.compareTo(BigDecimal.ZERO) <= 0) {
            ptintegralMapper.insert(buildPtIntegral(context + "[正常]", userId, 0, 0, needMoney));
            return;
        }
        BigDecimal isFreeze = needMoney.subtract(freeze);
        if (isFreeze.compareTo(BigDecimal.ZERO) <= 0 /*冻结的充足*/) {
            ptintegralMapper.insert(buildPtIntegral(context + "[冻结]", userId, 1, 0, needMoney));
        } else {
            if (freeze.compareTo(BigDecimal.ZERO) > 0) {
                ptintegralMapper.insert(buildPtIntegral(context + "[冻结]", userId, 1, 0, freeze));
            }

            ptintegralMapper.insert(buildPtIntegral(context + "[正常]", userId, 0, 0, isFreeze));

        }
    }

    public Ptintegral buildPtIntegral(final String context, final String userId,
                                      final Integer type, final Integer status, final BigDecimal money){
        final Ptintegral ptintegral = new Ptintegral();
        ptintegral.setContext(context);
        ptintegral.setCreateTime(DateUtil.date());
        ptintegral.setSub(userId);
        ptintegral.setType(type);
        ptintegral.setStatus(status);
        ptintegral.setMoney(money);
        return ptintegral;
    }

    public SelfOrder buildOrder(final Commodity commodity, final Subscribers subscribers, final PartakerConfirmPayDTO partakerConfirmPayDTO){
        final String orderNo = OrderGenContext.generateOrderNo();
        log.warn("orderNo: {}", orderNo);
        return SelfOrder
                .builder()
                .parentId(commodity.getParentId())
                .shopId(commodity.getShopId())
                .commodityId(commodity.getId())
                .commoditySubarea(commodity.getCommoditySubarea())
                .userId(subscribers.getId())
                .mobile(subscribers.getMobile())
                .number(partakerConfirmPayDTO.getNumber())
                .payWay(partakerConfirmPayDTO.getPayWay())
                .orderNo(orderNo)
                .parentOrderNo(partakerConfirmPayDTO.getTeamOrderNo())
                .status(1)
                .recipientsName(partakerConfirmPayDTO.getRecipientsName())
                .recipientsMobile(partakerConfirmPayDTO.getRecipientsMobile())
                .recipientsAddress(partakerConfirmPayDTO.getRecipientsAddress())
                .remark(partakerConfirmPayDTO.getRemark())
                .regimental(partakerConfirmPayDTO.getRegimental())
                .createTime(DateUtil.date())
                .build();
    }

    @Transactional(noRollbackFor = {SelfRuntimeOkException.class})
    public void partakerOrder(final PartakerConfirmPayDTO partakerConfirmPayDTO,
                              final BuildCreateOrderContext buildCreateOrderContext,
                              final BuildPartakerContext buildPartakerContext) throws Exception {
        if (partakerConfirmPayDTO.getPayWay() == 3) {
            throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("暂不支持此支付方式"));
        }

        check(partakerConfirmPayDTO, this::context, buildCreateOrderContext, buildPartakerContext);
    }

    public void check(final PartakerConfirmPayDTO partakerConfirmPayDTO,
                      final BuildCheckOrderContext buildCheckOrderContext,
                      final BuildCreateOrderContext buildCreateOrderContext,
                      final BuildPartakerContext buildPartakerContext) throws Exception {
        final Subscribers subscribers = subscribersMapper.selectByPrimaryKey(partakerConfirmPayDTO.getUserId());
            Optional.ofNullable(subscribers).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("用户不存在")));
        final Commodity commodity = commodityMapper.selectById(partakerConfirmPayDTO.getCommodityId());
        Optional.ofNullable(commodity).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("商品信息错误")));
        if (commodity.getCommoditySubarea() != 0) {
            throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("此商品无法参与拼团!"));
        }
        final Integer stock = commodity.getCommodityStock() - partakerConfirmPayDTO.getNumber();
        if (stock.compareTo(0) < 0) {
            throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("库存不足"));
        }
    /*    PtCurrent ptCurrent = iPtCurrentService.selectCurrentByUserIdAndGoodsId(subscribers.getId(), String.valueOf(commodity.getId()));
        if (ptCurrent != null &&StringUtils.isEmpty(ptCurrent.getSub4())) {
            throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("该用户已经参与拼团该商品哦"));
        }*/
        if (!StringUtils.isEmpty(partakerConfirmPayDTO.getRegimental())) {
            PtCurrent ptCurrentSub1 = iPtCurrentService.selectCurrentByUserIdAndOrderNo(partakerConfirmPayDTO.getRegimental(), String.valueOf(partakerConfirmPayDTO.getTeamOrderNo()));
            if (ptCurrentSub1 == null) {
                logger.warn("团不存在信息:团长ID:{},团长订单号:{}",partakerConfirmPayDTO.getRegimental(),partakerConfirmPayDTO.getTeamOrderNo());
                throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("团不存在哦"));
            }
            if (partakerConfirmPayDTO.getUserId().equals(ptCurrentSub1.getSub1())){
                throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("您是团长不可加团哦"));
            }
            //先判断用户是否已经在团内
            boolean existTeam = partakerConfirmPayDTO.getUserId().equals(ptCurrentSub1.getSub1()) || partakerConfirmPayDTO.getUserId().equals(ptCurrentSub1.getSub2()) || partakerConfirmPayDTO.getUserId().equals(ptCurrentSub1.getSub3()) ||partakerConfirmPayDTO.getUserId().equals(ptCurrentSub1.getSub4());
            if (existTeam) throw new BaseException(ResponseResultUtils.getResponseResultF("您已经在团内无法重复参团"));
            logger.warn("拼团提示:用户id为{}的人员即将进入团长id为{}，订单号为{}的团队",partakerConfirmPayDTO.getUserId(),partakerConfirmPayDTO.getRegimental(),partakerConfirmPayDTO.getTeamOrderNo());
        }
        buildCheckOrderContext.buildCheckContext(partakerConfirmPayDTO, subscribers, commodity, buildCreateOrderContext, buildPartakerContext);
    }

    public void context(final PartakerConfirmPayDTO partakerConfirmPayDTO,
                        final Subscribers subscribers,
                        final Commodity commodity,
                        final BuildCreateOrderContext buildCreateOrderContext,
                        final BuildPartakerContext buildPartakerContext) throws Exception {
        final BigDecimal sumMoney = commodity.getCommodityRealPrice().multiply(new BigDecimal(partakerConfirmPayDTO.getNumber()));
        final BigDecimal userMoney = iPtintegralService.getTotalMoneyByUserId(partakerConfirmPayDTO.getUserId(), null);

        final SelfOrder selfOrder = buildOrder(commodity, subscribers, partakerConfirmPayDTO);

        BigDecimal subtractMoney = sumMoney.subtract(userMoney);
        log.warn("subtractMoney: {}", subtractMoney);
        if (subtractMoney.compareTo(BigDecimal.ZERO) <= 0 /*奖励金充足*/) {
            deductExpenses("参团扣除", subscribers.getId(), sumMoney);

            buildPartakerContext.buildPartakerContext(subscribers.getId(), partakerConfirmPayDTO.getRegimental(), String.valueOf(commodity.getId()),partakerConfirmPayDTO.getTeamOrderNo(), selfOrder.getOrderNo());

            selfOrder.setRealPrice(new BigDecimal(0));
            selfOrder.setDiscountPrice(sumMoney);
            selfOrder.setPayTime(DateUtil.date());
            selfOrder.setStatus(6);
            selfOrder.setIsPartaker(0);
            selfOrder.setCallnum(partakerConfirmPayDTO.getCallnum());
            selfOrderMapper.insert(selfOrder);

            lockStockService.updateStockPartaker(commodity.getId(), selfOrder);
            throw new SelfRuntimeOkException(ResponseResultUtils.getResponseResultS("参团成功"));
        }

        final PayDeal payDeal = PayDeal.builder()
                .createTime(DateUtil.date())
                .money(subtractMoney)
                .payWay(partakerConfirmPayDTO.getPayWay())
                .status(0)
                .userId(subscribers.getId())
                .parentId(subscribers.getParentid())
                .orderNo(selfOrder.getOrderNo())
                .build();
        payDealMapper.insert(payDeal);

        selfOrder.setRealPrice(subtractMoney);
        selfOrder.setDiscountPrice(userMoney);
        selfOrderMapper.insert(selfOrder);

        buildCreateOrderContext.buildCreateOrderContext(selfOrder, commodity, payDeal);
    }

    public void checkOrderPay(final OrderConfirmPayDTO orderConfirmPayDTO, final BuildOrderPayContext buildOrderPayContext) throws Exception{
        final SelfOrder selfOrder = selfOrderMapper.selectOne(new LambdaQueryWrapper<SelfOrder>()
                .eq(SelfOrder::getId, orderConfirmPayDTO.getOrderId())
                .eq(SelfOrder::getUserId, orderConfirmPayDTO.getUserId())
        );
        Optional.ofNullable(selfOrder).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("订单信息错误")));

        if (selfOrder.getStatus() != 1) {
            throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("订单状态错误"));
        }

        if (selfOrder.getDiscountPrice().compareTo(BigDecimal.ZERO) > 0) {
            final BigDecimal userMoney = iPtintegralService.getTotalMoneyByUserId(orderConfirmPayDTO.getUserId(), null);
            if (selfOrder.getDiscountPrice().compareTo(userMoney) > 0) {
                throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("积分不足，无法支付！"));
            }
        }

        final PayDeal payDeal = payDealMapper.selectOne(new LambdaQueryWrapper<PayDeal>().eq(PayDeal::getOrderNo, selfOrder.getOrderNo()));
        Optional.ofNullable(payDeal).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("交易信息缺失！")));

        if (payDeal.getStatus() != 0) {
            throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("交易状态错误！"));
        }

        buildOrderPayContext.buildOrderPayContext(selfOrder, payDeal);
    }
}
